/*
 * ToolsFunctions.c
 *	Functions for general and parsing use
 *  Created on: 23 nov. 2009
 *      Authors: Bruno CAUSSIN 				<caussin@ecole.ensicaen.fr>
 *      		 StÃ©phanie PLEYER			<pleyer@ecole.ensicaen.fr>
 *      		 Charles-Edouard VIDOINE	<vidoine@ecole.ensicaen.fr
 */
#include "ToolsFunctions.h"
#include <math.h>

char *str_replace(char *str, char *orig, char *rep)
{
	static char buffer[4096];
	char *p;

	if(!(p = strstr(str, orig)))  // Is 'orig' even in 'str'?
		return str;

	strncpy(buffer, str, p-str); // Copy characters from 'str' start to 'orig' st$
	buffer[p-str] = '\0';

	sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig));

	return buffer;
}

// takes the extension from a filename
char * extension(char * filename){
	char * extension = strrchr(filename, '.');
	if(extension != NULL)
	{
		// sauter le caractere point
		extension++;
		//printf("l'extension du fichier %s est %s\n", filename, extension);
	}
	return extension;
}

// functions to extract the wanted objects from an xml file

xmlDocPtr getdoc (char *docname) {
	xmlDocPtr doc;
	doc = xmlParseFile(docname);

	if (doc == NULL ) {
		fprintf(stderr,"Document not parsed successfully. \n");
		return NULL;
	}

	return doc;
}

xmlXPathObjectPtr getnodeset (xmlDocPtr doc, xmlChar *xpath){

	xmlXPathContextPtr context;
	xmlXPathObjectPtr result;


	context = xmlXPathNewContext(doc);
	if (context == NULL) {
		printf("Error in xmlXPathNewContext\n");
		return NULL;
	}
	result = xmlXPathEvalExpression(xpath, context);
	xmlXPathFreeContext(context);
	if (result == NULL) {
		printf("Error in xmlXPathEvalExpression\n");
		return NULL;
	}
	if(xmlXPathNodeSetIsEmpty(result->nodesetval)){
		xmlXPathFreeObject(result);
		//printf("No result\n");
		return NULL;
	}
	return result;
}

/** Parses an xml file, seeks the value of the names of the objects, if one at least is the wanted class
 * then writes the path of the corresponding image to the file fichier.
 *
 * @filepath path to the xml file
 * @classe wanted classe
 * @fichier file where to write
 */
void analyseXMLFile(char * filepath,char * classe, FILE * fichier){

	int i, found;
	char *imgpath; // path of the image
	xmlDocPtr doc; // xml document
	xmlChar *xpath = (xmlChar*) "//object/name"; // path of the information (class) we want to find
	xmlNodeSetPtr nodeset;
	xmlXPathObjectPtr result;
	xmlChar *keyword; // value we want to compare the found classes with

	doc = getdoc(filepath);
	result = getnodeset (doc, xpath);

	if (result) { // if there is the wanted balises in the document

		nodeset = result->nodesetval; // we store them
		found = 0;
		for (i=0; i < nodeset->nodeNr; i++) { // we browse them
			keyword = xmlNodeListGetString(doc, nodeset->nodeTab[i]->xmlChildrenNode, 1);
			//printf("keyword: %s\n", keyword);

			if (strcmp(keyword,classe) == 0){ // if a balise describes the wanted object
				found++;
				//printf("found %s\n",filepath);
				break;
				//printf("-*--> %s\n", filepath);
			}

			free(keyword);
			//xmlFree(keyword);
		}

		// We write the class and the name of the corresponding image
		imgpath = str_replace (filepath, "xml", "jpg");
		imgpath = str_replace (imgpath, "Annotations", "JPEGImages");
		if (found >= 1){
			fprintf(fichier, "%d ", 1); // classe = 1 if the object was found
		}else {
			fprintf(fichier, "%d ", -1); // classe = -1 if the object was not found
		}
		fprintf(fichier, "%s\n", imgpath);

		xmlXPathFreeObject (result);
	}
	xmlFreeDoc(doc);
	xmlCleanupParser();
	//filepath="";

}

/** Browse a directory containing xml files and writes the name of the matching images to the file fichier.
 *
 * @param rep directory containing the xml files
 * @param dirname name of the above directory
 * @param classe wanted class
 * @fichier file where to write
 *
 */
void analyseDir(DIR * rep, char * dirname, char * classe, FILE * fichier){

	int i;
	char *filepath; // path of the browsed file
	struct dirent * ent;
	filepath = (char *) calloc (FILEPATH_MAX_SIZE, sizeof(char));

	while ((ent = readdir(rep)) != NULL) // tant qu'on n'a pas parcouru tout le dossier
	{
		// dans filepath sera stockÃ© le nom du fichier image contenant l'objet de la classe recherchÃ©e
		strcpy(filepath,dirname);
		// on ajoute Ã©ventuellement un / Ã  la fin du chemin pour pouvoir y concatÃ©ner ensuite le nom du fichier
		i = strlen(filepath)-1;
		if (filepath[i] != '/')
			strcat(filepath,"/");
		strcat(filepath,ent->d_name);
		//printf("---> %s\n", filepath);

		if (extension(ent->d_name) != NULL){
			if (strcmp(extension(ent->d_name),"xml") == 0){
				analyseXMLFile(filepath, classe, fichier);
			}
		}

	}
	closedir(rep);
	free(filepath);
}

// distance between 2 vectors of dimension dim
double distanceVect(double* v1, double* v2, int dim) {
	double distance = 0;
	int i;
	for (i = 0; i < dim; i++) {
		distance += (v1[i] - v2[i]) * (v1[i] - v2[i]);
	}
	return distance;
}

/** Seek for annotations containing the "classe" name in a directory and writes the names of the positive jpeg corresponding images to a text file.
 * The name of the text file is <classe>.txt
 *
 * More precisely, seeks for xml files containing something like :
 * <object><name>class</name></object>
 * where class = the class we want
 *
 * @param dirname directory containing the xml file
 * @param classe name of the wanted class
 *
 */
void seekForClass(char * dirname, char * classe){

	DIR * rep = opendir(dirname);
	FILE* fichier = NULL;
	char * filename = (char*)calloc(sizeof(classe)+4,sizeof(char));
	strncpy(filename,classe,sizeof(classe));
	strcat(filename,".txt");
	fichier = fopen(filename, "w"); // file in which we aim to write the names of the files with wanted objects

	if (fichier != NULL)
	{
		// On peut lire et Ã©crire dans le fichier
		if (rep != NULL)
		{
			analyseDir(rep, dirname, classe, fichier);
		}
		fclose(fichier);
	}
	else
	{
		// On affiche un message d'erreur si on veut
		printf("Impossible d'ouvrir le fichier test.txt");
		fclose(fichier);
	}
	free(filename);
}

/**
 * Normalisation
 */
void normalize(double ** mat,int nbElements){
	int i,j;
	double sum=0;
	for(i=0;i<nbElements;i++){
		sum=0;
		for(j=0;j<DIMENSION;j++){
			sum+=pow(mat[i][j],2);
		}
		for(j=0;j<DIMENSION;j++){
			mat[i][j] = (double)((double)mat[i][j]/(double)sqrt(sum));
		}
	}
}

/**
 * Normalisation
 */
void normalize2(double * mat){
	int j;
	double sum=0;

	for(j=0;j<DIMENSION;j++){
		sum+=pow(mat[j],2);
	}
	for(j=0;j<DIMENSION;j++){
		mat[j] = (double)((double)mat[j]/(double)sqrt(sum));
	}

}

